/*
 Third-party chacha20 lib from https://github.com/Yawning/chacha20
*/
package crypto

import (
	"crypto/rand"
	"iox/crypto/chacha20"
)

var (
	SECRET_KEY []byte
	NONCE      []byte
)

func expand32(key []byte) ([]byte, []byte) {
	if len(key) >= 0x20 {
		return key[:0x20], append(key[:0xC], key[len(key)-0xC:]...)
	}

	var c byte = 0x20 - byte(len(key)&0x1F)

	for i := 0; i < int(c); i++ {
		key = append(key, c)
	}
	return key[:0x20], append(key[:0xC], key[len(key)-0xC:]...)
}

func ExpandKey(key []byte) {
	SECRET_KEY, NONCE = expand32(key)
}

type Cipher struct {
	c *chacha20.Cipher
}

func NewCipherPair() (*Cipher, *Cipher, error) {
	ccA, err := chacha20.New(SECRET_KEY, NONCE)
	if err != nil {
		return nil, nil, err
	}
	ccB, err := chacha20.New(SECRET_KEY, NONCE)
	if err != nil {
		return nil, nil, err
	}

	return &Cipher{c: ccA}, &Cipher{c: ccB}, nil
}

func RandomNonce() ([]byte, error) {
	iv := make([]byte, 0x18)
	_, err := rand.Read(iv)
	if err != nil {
		return nil, err
	}
	return iv, nil
}

func NewCipher(nonce []byte) (*Cipher, error) {
	cc, err := chacha20.New(SECRET_KEY, nonce)
	if err != nil {
		return nil, err
	}

	return &Cipher{
		c: cc,
	}, nil
}

func (c Cipher) StreamXOR(dst []byte, src []byte) {
	c.c.XORKeyStream(dst, src)
}
